﻿using MvvmCross.Platform;
using MvvmCross.Plugins.Messenger;
using MvvmCross.Core.ViewModels;
using Sidvall.Data;
using Sidvall.WorkItemManager.UI.Entities;
using Sidvall.WorkItemManager.UI.Messaging;
using Sidvall.WorkItemManager.Workflow;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Sidvall.WorkItemManager.UI.ViewModels
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
    public partial class WorkerViewModel
    {
        #region Public Members

        #region Title

        private string _Title;
        public string Title
        {
            get
            {
                return _Title;
            }
            set
            {
                _Title = value;
                RaisePropertyChanged("Title");
            }
        }

        #endregion
        #region TreeItems

        private TreeItemCollection _TreeItems;
        public TreeItemCollection TreeItems
        {
            get
            {
                return _TreeItems;
            }
            set
            {
                if (_TreeItems != null)
                    _TreeItems.CollectionChanging -= OnTreeItemsCollectionChanging;
                _TreeItems = value;
                if (_TreeItems != null)
                    _TreeItems.CollectionChanging += OnTreeItemsCollectionChanging;
                RaisePropertyChanged("TreeItems");
            }
        }

        #endregion
        #region ActiveServerConnection

        private ServerConnection _ActiveServerConnection;
        public ServerConnection ActiveServerConnection
        {
            get
            {
                return _ActiveServerConnection;
            }
            set
            {
                _ActiveServerConnection = value;
                if (_ActiveServerConnection != null)
                {
                    if (_ActiveWorker != null)
                        _ActiveWorker.PropertyChanged -= OnActiveWorkerPropertyChanged;
                    _ActiveWorker = null;
                    if (_ActiveWorkItem != null)
                        _ActiveWorkItem.PropertyChanged -= OnActiveWorkItemPropertyChanged;
                    _ActiveWorkItem = null;
                }
                RaiseAllPropertiesChanged();
            }
        }

        #endregion
        #region ActiveServerManager

        private Sidvall.WorkItemManager.UI.Entities.ServerManager _ActiveServerManager;
        public Sidvall.WorkItemManager.UI.Entities.ServerManager ActiveServerManager
        {
            get
            {
                return _ActiveServerManager;
            }
            set
            {
                _ActiveServerManager = value;
                RaiseAllPropertiesChanged();
            }
        }

        #endregion
        #region ActiveWorker

        private Worker _ActiveWorker;
        public Worker ActiveWorker
        {
            get
            {
                return _ActiveWorker;
            }
            set
            {
                if (_ActiveWorker != null)
                    _ActiveWorker.PropertyChanged -= OnActiveWorkerPropertyChanged;
                _ActiveWorker = value;
                if (_ActiveWorker != null)
                {
                    _ActiveWorker.PropertyChanged += OnActiveWorkerPropertyChanged;
                    _ActiveServerConnection = null;
                    if (_ActiveWorkItem != null)
                        _ActiveWorkItem.PropertyChanged -= OnActiveWorkItemPropertyChanged;
                    _ActiveWorkItem = null;
                }
                RaiseAllPropertiesChanged();
            }
        }

        #endregion
        #region ActiveWorkItem

        private WorkItem _ActiveWorkItem;
        public WorkItem ActiveWorkItem
        {
            get
            {
                return _ActiveWorkItem;
            }
            set
            {
                if (_ActiveWorkItem != null)
                    _ActiveWorkItem.PropertyChanged -= OnActiveWorkItemPropertyChanged;
                _ActiveWorkItem = value;
                if (_ActiveWorkItem != null)
                {
                    _ActiveWorkItem.PropertyChanged += OnActiveWorkItemPropertyChanged;
                    InitializeLog();
                }
                _ActiveServerConnection = null;
                if (_ActiveWorker != null)
                    _ActiveWorker.PropertyChanged -= OnActiveWorkerPropertyChanged;
                _ActiveWorker = null;
                RaiseAllPropertiesChanged();
            }
        }

        #endregion
        #region ActiveTreeItem

        private TreeItem _ActiveTreeItem;
        public TreeItem ActiveTreeItem
        {
            get
            {
                return _ActiveTreeItem;
            }
            set
            {
                _ActiveTreeItem = value;
                if (_ActiveTreeItem == null)
                {
                    this.Title = "Workers";
                }
                else
                {
                    this.Title = _ActiveTreeItem.FullName;
                }
                RaisePropertyChanged("ActiveTreeItem");
            }
        }

        #endregion
        #region ActiveWorkItemCondition

        private WorkItemWorkCondition _ActiveWorkItemCondition;
        public WorkItemWorkCondition ActiveWorkItemCondition
        {
            get
            {
                return _ActiveWorkItemCondition;
            }
            set
            {
                _ActiveWorkItemCondition = value;
                RaisePropertyChanged("ActiveWorkItemCondition");
            }
        }

        #endregion
        #region LastUpdated

        private System.DateTime? _LastUpdated;
        public System.DateTime? LastUpdated
        {
            get
            {
                return _LastUpdated;
            }
            set
            {
                _LastUpdated = value;
                RaisePropertyChanged("LastUpdated");
            }
        }

        #endregion
        #region LastUpdatedException

        private string _LastUpdatedException;
        public string LastUpdatedException
        {
            get
            {
                return _LastUpdatedException;
            }
            set
            {
                _LastUpdatedException = value;
                RaisePropertyChanged("LastUpdatedException");
                RaisePropertyChanged("LastUpdatedExceptionIsVisible");
            }
        }

        #endregion
        #region IdleTime

        public System.TimeSpan? IdleTime
        {
            get
            {
                return Sidvall.WorkItemManager.SystemContext.Current.EntityFacade.WorkItemManager.GetIdleTime(this.ActiveWorkItem);
            }
        }

        #endregion
        #region InformationIsVisible

        public bool InformationIsVisible
        {
            get
            {
                if (_WorkItemIsVisible)
                    return false;
                if ((this.ServerIsVisible) || (this.WorkerIsVisible) || (this.WorkItemIsVisible))
                    return false;
                return true;
            }
        }

        #endregion
        #region ServerIsVisible

        public bool ServerIsVisible
        {
            get
            {
                if (_WorkItemIsVisible)
                    return false;
                if (this.ActiveServerConnection != null)
                    return true;
                return false;
            }
        }

        #endregion
        #region WorkerIsVisible

        public bool WorkerIsVisible
        {
            get
            {
                if (_WorkItemIsVisible)
                    return false;
                if (this.ActiveWorker != null)
                    return true;
                return false;
            }
        }

        #endregion
        #region WorkItemIsVisible

        private bool _WorkItemIsVisible = true;
        public bool WorkItemIsVisible
        {
            get
            {
                if (_WorkItemIsVisible)
                    return true;
                if (this.ActiveWorkItem != null)
                    return true;
                return false;
            }
            set
            {
                _WorkItemIsVisible = value;
                RaisePropertyChanged("WorkItemIsVisible");
            }
        }

        #endregion
        #region ConditionListIsVisible

        private bool _ConditionListIsVisible = true;
        public bool ConditionListIsVisible
        {
            get
            {
                return _ConditionListIsVisible;
            }
            set
            {
                _ConditionListIsVisible = value;
                RaisePropertyChanged("ConditionListIsVisible");
            }
        }

        #endregion
        #region LastUpdatedExceptionIsVisible

        public bool LastUpdatedExceptionIsVisible
        {
            get
            {
                if (string.IsNullOrWhiteSpace(this.LastUpdatedException))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanSave

        public bool CanSave
        {
            get
            {
                if (this.ActiveWorker != null)
                {
                    if (!this.ActiveWorker.DataRowStateIsDirty)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.Worker, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                else if (this.ActiveWorkItem != null)
                {
                    if (!this.ActiveWorkItem.DataRowStateIsDirty)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                return false;
            }
        }

        #endregion
        #region CanDelete

        public bool CanDelete
        {
            get
            {
                if (this.ActiveWorker != null)
                {
                    if (this.ActiveWorker.WorkerId == null)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.Worker, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                else if (this.ActiveWorkItem != null)
                {
                    if (this.ActiveWorkItem.WorkItemId == null)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                return false;
            }
        }

        #endregion
        #region CanDeleteLogs

        public bool CanDeleteLogs
        {
            get
            {
                if (this.ActiveWorkItem == null)
                    return false;
                if (this.ActiveWorkItem.WorkItemId == null)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanEdit

        public bool CanEdit
        {
            get
            {
                if (this.ActiveWorker != null)
                {
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.Worker, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                else if (this.ActiveWorkItem != null)
                {
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                return false;
            }
        }

        #endregion
        #region CanReset

        public bool CanReset
        {
            get
            {
                if (this.ActiveServerConnection != null)
                {
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.Worker, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                else if (this.ActiveWorker != null)
                {
                    if (this.ActiveWorker.WorkerId == null)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.Worker, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                else if (this.ActiveWorkItem != null)
                {
                    if (this.ActiveWorkItem.WorkItemId == null)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                return false;
            }
        }

        #endregion
        #region CanAddTreeItem

        public bool CanAddTreeItem
        {
            get
            {
                if (this.ActiveServerConnection != null)
                {
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.Worker, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                else if (this.ActiveWorker != null)
                {
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                return false;
            }
        }

        #endregion
        #region CanCancelTreeItem

        public bool CanCancelTreeItem
        {
            get
            {
                if (this.ActiveWorkItem == null)
                    return false;
                if (this.ActiveWorkItem.WorkItemId == null)
                    return false;
                if (!this.ActiveWorkItem.IsEnabled)
                    return false;
                if (this.ActiveWorkItem.IsCanceled)
                    return false;
                if (this.ActiveWorkItem.WorkItemStatusId == Workflow.WorkItemStatus.Idle)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanEnableTreeItem

        public bool CanEnableTreeItem
        {
            get
            {
                if (this.ActiveWorker != null)
                {
                    if (this.ActiveWorker.WorkerId == null)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.Worker, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                else if (this.ActiveWorkItem != null)
                {
                    if (this.ActiveWorkItem.WorkItemId == null)
                        return false;
                    if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                        return false;
                    return true;
                }
                return false;
            }
        }

        #endregion
        #region CanRunTreeItem

        public bool CanRunTreeItem
        {
            get
            {
                if (this.ActiveWorkItem == null)
                    return false;
                if (this.ActiveWorkItem.WorkItemId == null)
                    return false;
                if (!this.ActiveWorkItem.IsEnabled)
                    return false;
                if (this.ActiveWorkItem.IsCanceled)
                    return false;
                if (this.ActiveWorkItem.ForceExecution)
                    return false;
                if (this.ActiveWorkItem.WorkItemStatusId != Workflow.WorkItemStatus.Idle)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanDeleteRetryPolicy

        public bool CanDeleteRetryPolicy
        {
            get
            {
                if (this.ActiveWorkItem == null)
                    return false;
                if (this.ActiveWorkItem.WorkRetryPolicyId == null)
                    return false;
                if (!this.ActiveServerManager.ServerContent.ContainsResourceItem(Sidvall.WorkItemManager.Data.Model.DomainObjects.WorkItem, Sidvall.Security.Operations.UpdateItems))
                    return false;
                return true;
            }
        }

        #endregion
        #region CanPageBackLog

        public bool CanPageBackLog
        {
            get
            {
                return this.LogCurrentPage > 1;
            }
        }

        #endregion
        #region CanPageForwardLog

        public bool CanPageForwardLog
        {
            get
            {
                return this.LogCurrentPage < this.LogPageCount;
            }
        }

        #endregion
        #region AddTreeItemCaption

        public string AddTreeItemCaption
        {
            get
            {
                if (this.ActiveServerConnection != null)
                    return "Add Worker";
                if (this.ActiveWorker != null)
                    return "Add Task";
                return null;
            }
        }

        #endregion
        #region TreeItemIsEnabled

        public bool TreeItemIsEnabled
        {
            get
            {
                if (this.ActiveWorker != null)
                    return this.ActiveWorker.IsEnabled;
                if (this.ActiveWorkItem != null)
                    return this.ActiveWorkItem.IsEnabled;
                return false;
            }
        }

        #endregion
        #region ThreadActions

        private Sidvall.Data.KeyValueCollection<string, Workflow.ThreadAction> _ThreadActions;
        public Sidvall.Data.KeyValueCollection<string, Workflow.ThreadAction> ThreadActions
        {
            get
            {
                if (_ThreadActions == null)
                    this.ThreadActions = Sidvall.Data.KeyValueManager.FromEnum<Sidvall.WorkItemManager.Workflow.ThreadAction>();
                return _ThreadActions;
            }
            set
            {
                _ThreadActions = value;
                RaisePropertyChanged("ThreadActions");
            }
        }

        #endregion
        #region WorkItemStatuses

        private Sidvall.Data.KeyValueCollection<string, Workflow.WorkItemStatus> _WorkItemStatuses;
        public Sidvall.Data.KeyValueCollection<string, Workflow.WorkItemStatus> WorkItemStatuses
        {
            get
            {
                if (_WorkItemStatuses == null)
                    this.WorkItemStatuses = Sidvall.Data.KeyValueManager.FromEnum<Sidvall.WorkItemManager.Workflow.WorkItemStatus>();
                return _WorkItemStatuses;
            }
            set
            {
                _WorkItemStatuses = value;
                RaisePropertyChanged("WorkItemStatuses");
            }
        }

        #endregion
        #region LogModes

        private Sidvall.UI.Entities.SelectableKeyValueCollection<string, Workflow.LogModes> _LogModes;
        public Sidvall.UI.Entities.SelectableKeyValueCollection<string, Workflow.LogModes> LogModes
        {
            get
            {
                if (_LogModes == null)
                {
                    this.LogModes = Sidvall.UI.Entities.SelectableKeyValueManager.CreateFromEnum<Workflow.LogModes>(false);
                    this.LogModes.ChildChanged += OnLogModesChildChanged;
                }
                return _LogModes;
            }
            set
            {
                _LogModes = value;
                RaisePropertyChanged("LogModes");
            }
        }

        #endregion
        #region LogCaption

        public string LogCaption
        {
            get
            {
                if (this.ActiveWorkItem == null)
                    return null;
                if (this.ActiveWorkItem.WorkItemLogs == null)
                    return null;
                if (this.ActiveWorkItem.WorkItemLogs.TotalRowCount <= this.LogPageSize)
                    return this.ActiveWorkItem.WorkItemLogs.Count.ToString() + " (of " + this.ActiveWorkItem.WorkItemLogs.TotalRowCount.ToString() + ")";
                return this.LogCurrentStartPosition.ToString() + " - " + this.LogCurrentEndPosition.ToString()
                    + " (of " + this.ActiveWorkItem.WorkItemLogs.TotalRowCount.ToString() + ")";
            }
        }

        #endregion
        #region LogFilterAll

        private bool _LogFilterAll;
        public bool LogFilterAll
        {
            get
            {
                return _LogFilterAll;
            }
            set
            {
                _LogFilterAll = value;
                RaisePropertyChanged("LogFilterAll");
                if (_LogFilterAll)
                {
                    this.LogFilterErrors = false;
                    this.LogFilterMessages = false;
                }
            }
        }

        #endregion
        #region LogFilterErrors

        private bool _LogFilterErrors;
        public bool LogFilterErrors
        {
            get
            {
                return _LogFilterErrors;
            }
            set
            {
                _LogFilterErrors = value;
                RaisePropertyChanged("LogFilterErrors");
                if (_LogFilterErrors)
                {
                    this.LogFilterAll = false;
                    this.LogFilterMessages = false;
                }
            }
        }

        #endregion
        #region LogFilterMessages

        private bool _LogFilterMessages;
        public bool LogFilterMessages
        {
            get
            {
                return _LogFilterMessages;
            }
            set
            {
                _LogFilterMessages = value;
                RaisePropertyChanged("LogFilterMessages");
                if (_LogFilterMessages)
                {
                    this.LogFilterAll = false;
                    this.LogFilterErrors = false;
                }
            }
        }

        #endregion

        #region ExportSettingsCommand

        public ICommand ExportSettingsCommand
        {
            get
            {
                return new MvxCommand(async () => await ExportSettingsAsync());
            }
        }

        #endregion
        #region ExportSettingsAsync

        public async Task ExportSettingsAsync()
        {
            if (this.ActiveWorkItem == null)
                return;
            var item = new Net.Services.V1.WorkItem();
            item.Import(this.ActiveWorkItem, Sidvall.Data.CopySettings.FullCopyAll(Sidvall.Data.DataRowContextOption.None, null));
            await ViewModelManager.ExportSettingsAsync("Task_" + this.ActiveWorkItem.Name + ".txt", item);
        }

        #endregion
        #region ImportSettingsCommand

        public ICommand ImportSettingsCommand
        {
            get
            {
                return new MvxCommand(async () => await ImportSettingsAsync());
            }
        }

        #endregion
        #region ImportSettingsAsync

        public async Task ImportSettingsAsync()
        {
            Task task = null;
            if (this.ActiveWorker == null)
                return;
            try
            {
                var content = await ViewModelManager.ImportSettingsAsync();
                if (string.IsNullOrWhiteSpace(content))
                    return;
                var data = Sidvall.Serialization.SerializerManager.Current.Deserialize<Net.Services.V1.WorkItem>(content);
                var item = new Sidvall.WorkItemManager.UI.Entities.WorkItem();
                var copySettings = CopySettings.FullCopyAll(Sidvall.Data.DataRowContextOption.None, null);
                item.Import(data, copySettings);
                item.ServerConnectionId = this.ActiveWorker.ServerConnectionId;
                item.WorkerId = this.ActiveWorker.WorkerId.Value;
                item = await item.SaveItemAsync();
                await ReloadAsync();
                var treeItem = (from o in this.TreeItems
                                where (o.ServerConnectionId == item.ServerConnectionId) && (o.ItemId == item.WorkItemId)
                                select o).FirstOrDefault();
                if (treeItem != null)
                    this.ActiveTreeItem = treeItem;
            }
            catch (System.Exception ex)
            {
                task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
            }
            if (task != null)
                await task;
        }

        #endregion

        #region SelectType

        public ICommand SelectTypeCommand
        {
            get
            {
                return new MvxCommand(async () => await SelectTypeAsync());
            }
        }
        public async Task SelectTypeAsync()
        {
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    InitializeType();
                }
                catch (System.Exception ex)
                {
                    await Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
            }
        }

        #endregion

        #region AddConditionCommand

        public ICommand AddConditionCommand
        {
            get
            {
                return new MvxCommand(AddCondition);
            }
        }

        #endregion
        #region AddCondition

        public void AddCondition()
        {
            WorkItemWorkCondition item;

            if (this.ActiveWorkItem == null)
                return;
            if (this.ActiveTreeItem.Conditions.Count == 0)
                return;

            item = new WorkItemWorkCondition()
            {
                InvalidAction = Workflow.ThreadAction.ContinueWithNextWorkItem,
                IsEnabled = true,
                IsEnabledOnRetry = false,
                WorkConditionId = this.ActiveTreeItem.Conditions[0].WorkConditionId.Value,
            };
            if (this.ActiveWorkItem.WorkItemId != null)
                item.WorkItemId = this.ActiveWorkItem.WorkItemId.Value;
            this.ActiveWorkItem.WorkItemWorkConditions.Add(item);
            this.ActiveWorkItemCondition = item;
            InitializeCondition();
            this.ConditionListIsVisible = false;
        }

        #endregion
        #region DeleteConditionCommand

        public ICommand DeleteConditionCommand
        {
            get
            {
                return new MvxCommand<WorkItemWorkCondition>(DeleteCondition);
            }
        }

        #endregion
        #region DeleteCondition

        public void DeleteCondition(WorkItemWorkCondition item)
        {
            if (this.ActiveWorkItem == null)
                return;
            if (item == null)
                return;
            this.ActiveWorkItem.WorkItemWorkConditions.Remove(item);
        }

        #endregion
        #region EditConditionCommand

        public ICommand EditConditionCommand
        {
            get
            {
                return new MvxCommand<WorkItemWorkCondition>(EditCondition);
            }
        }

        #endregion
        #region EditCondition

        public void EditCondition(WorkItemWorkCondition item)
        {
            if (this.ActiveWorkItem == null)
                return;
            if (item == null)
                return;
            this.ActiveWorkItemCondition = item;
            InitializeCondition();
            this.ConditionListIsVisible = false;
        }

        #endregion
        #region ShowConditionListCommand

        public ICommand ShowConditionListCommand
        {
            get
            {
                return new MvxCommand(async () => await ShowConditionListAsync());
            }
        }

        #endregion
        #region ShowConditionListAsync

        public async Task ShowConditionListAsync()
        {
            this.ActiveWorkItemCondition.Description = await this.ActiveTreeItem.ServerManager.GetWorkItemConditionDescriptionAsync(this.ActiveWorkItem, this.ActiveWorkItemCondition);
            this.ConditionListIsVisible = true;
        }

        #endregion

        #region DeleteRetryPolicyCommand

        public ICommand DeleteRetryPolicyCommand
        {
            get
            {
                return new MvxCommand(DeleteRetryPolicy);
            }
        }

        #endregion
        #region DeleteRetryPolicy

        public void DeleteRetryPolicy()
        {
            if (this.ActiveWorkItem == null)
                return;
            this.ActiveWorkItem.WorkRetryPolicyId = null;
        }

        #endregion
        #region SelectRetryPolicyCommand

        public ICommand SelectRetryPolicyCommand
        {
            get
            {
                return new MvxCommand(async () => await SelectRetryPolicyAsync());
            }
        }

        #endregion
        #region SelectRetryPolicyAsync

        public async Task SelectRetryPolicyAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    InitializeRetryPolicy();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion

        #region ResetExecutionContextCommand

        public ICommand ResetExecutionContextCommand
        {
            get
            {
                return new MvxCommand(async () => await ResetExecutionContextAsync());
            }
        }

        #endregion
        #region ResetExecutionContextAsync

        public async Task ResetExecutionContextAsync()
        {
            Task task = null;
            CommandCriteria criteria;

            if (!this.CanDeleteLogs)
                return;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    criteria = ParameterManager.GetWorkItemResetCommand(this.ActiveWorkItem.ServerConnectionId.Value, new long[] { this.ActiveWorkItem.WorkItemId.Value },
                        null, false, true, false, null, false, null, null, null);
                    await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemManager.ExecuteAsync(criteria);
                    await ReloadAsync();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion

        #region DeleteLogCommand

        public ICommand DeleteLogCommand
        {
            get
            {
                return new MvxCommand<WorkItemLog>(DeleteLog);
            }
        }

        #endregion
        #region DeleteLog

        public void DeleteLog(WorkItemLog item)
        {
            if (this.ActiveWorkItem == null)
                return;
            if (item == null)
                return;
            this.ActiveWorkItem.WorkItemLogs.Remove(item);
        }

        #endregion
        #region DeleteLogsCommand

        public ICommand DeleteLogsCommand
        {
            get
            {
                return new MvxCommand(async () => await DeleteLogsAsync());
            }
        }

        #endregion
        #region DeleteLogsAsync

        public async Task DeleteLogsAsync()
        {
            Task task = null;
            if (!this.CanDeleteLogs)
                return;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemLogManager.DeleteItemsByWorkItemAsync(this.ActiveWorkItem.ServerConnectionId.Value,
                        this.ActiveWorkItem.WorkItemId.Value);
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
            await SelectTreeItemAsync();
        }

        #endregion
        #region PageBackLogCommand

        public ICommand PageBackLogCommand
        {
            get
            {
                return new MvxCommand(async () => await PageBackLogAsync());
            }
        }

        #endregion
        #region PageBackLogAsync

        public async Task PageBackLogAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    this.LogCurrentPage -= 1;
                    await RefreshLogAsync(this.ActiveWorkItem);
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region PageFirstLogCommand

        public ICommand PageFirstLogCommand
        {
            get
            {
                return new MvxCommand(async () => await PageFirstLogAsync());
            }
        }

        #endregion
        #region PageFirstLogAsync

        public async Task PageFirstLogAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    this.LogCurrentPage = 1;
                    await RefreshLogAsync(this.ActiveWorkItem);
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region PageForwardLogCommand

        public ICommand PageForwardLogCommand
        {
            get
            {
                return new MvxCommand(async () => await PageForwardLogAsync());
            }
        }

        #endregion
        #region PageForwardLogAsync

        public async Task PageForwardLogAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    this.LogCurrentPage += 1;
                    await RefreshLogAsync(this.ActiveWorkItem);
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region PageLastLogCommand

        public ICommand PageLastLogCommand
        {
            get
            {
                return new MvxCommand(async () => await PageLastLogAsync());
            }
        }

        #endregion
        #region PageLastLogAsync

        public async Task PageLastLogAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    this.LogCurrentPage = this.LogPageCount;
                    await RefreshLogAsync(this.ActiveWorkItem);
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region RefreshLogCommand

        public ICommand RefreshLogCommand
        {
            get
            {
                return new MvxCommand(async () => await RefreshLogAsync());
            }
        }

        #endregion
        #region RefreshLogAsync

        public async Task RefreshLogAsync()
        {
            Task task = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    await RefreshLogAsync(this.ActiveWorkItem);
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region OpenLogCommand

        public ICommand OpenLogCommand
        {
            get
            {
                return new MvxCommand<WorkItemLog>(async (o) => await OpenLogAsync(o));
            }
        }

        #endregion
        #region OpenLogAsync

        public async Task OpenLogAsync(WorkItemLog item)
        {
            Task task = null;
            if (item == null)
                return;
            using (var busyManager = new Sidvall.Data.BusyManager(this))
            {
                try
                {
                    await Sidvall.UI.SystemContext.Current.DialogManager.ShowMessageAsync("Log", item.ResultMessage, Sidvall.UI.Dialogs.MessageType.Information);
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion

        #region AddTreeItemCommand

        public ICommand AddTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await AddTreeItemAsync());
            }
        }

        #endregion
        #region AddTreeItemAsync

        public async Task AddTreeItemAsync()
        {
            Worker worker;
            WorkItem workItem;
            TreeItem treeItem;
            Task task = null;

            treeItem = null;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    if (this.ActiveServerConnection != null)
                    {
                        worker = new Worker()
                        {
                            ServerConnectionId = this.ActiveServerConnection.ServerConnectionId,
                            Name = "** New Worker **",
                            IsEnabled = true,
                        };
                        worker = await worker.SaveItemAsync();
                        await ReloadAsync();
                        treeItem = (from o in this.TreeItems
                                    where (o.ServerConnectionId == worker.ServerConnectionId) && (o.WorkerId == worker.WorkerId)
                                    select o).FirstOrDefault();
                    }
                    else if (this.ActiveWorker != null)
                    {
                        workItem = new WorkItem()
                        {
                            ServerConnectionId = this.ActiveWorker.ServerConnectionId,
                            Name = "** New Task **",
                            IsEnabled = true,
                            WorkerId = this.ActiveWorker.WorkerId.Value,
                            LogDayCount = 10,
                            SensorLogDayCount = 0,
                            ExecutionOrder = this.ActiveTreeItem.ChildCount + 1,
                        };
                        workItem = await workItem.SaveItemAsync();
                        await ReloadAsync();
                        treeItem = (from o in this.TreeItems
                                    where (o.ServerConnectionId == workItem.ServerConnectionId) && (o.ItemId == workItem.WorkItemId)
                                    select o).FirstOrDefault();
                    }
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
            if (treeItem != null)
                this.ActiveTreeItem = treeItem;
        }

        #endregion
        #region CancelTreeItemCommand

        public ICommand CancelTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await CancelTreeItemAsync());
            }
        }

        #endregion
        #region CancelTreeItemAsync

        public async Task CancelTreeItemAsync()
        {
            Task task = null;
            CommandCriteria criteria;

            if (!this.CanCancelTreeItem)
                return;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    criteria = ParameterManager.GetWorkItemResetCommand(this.ActiveWorkItem.ServerConnectionId.Value, new long[] { this.ActiveWorkItem.WorkItemId.Value },
                        null, false, false, false, null, false, null, true, null);
                    await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemManager.ExecuteAsync(criteria);
                    await ReloadAsync();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region EnableTreeItemCommand

        public ICommand EnableTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await EnableTreeItemAsync());
            }
        }

        #endregion
        #region EnableTreeItemAsync

        public async Task EnableTreeItemAsync()
        {
            CommandCriteria criteria;
            Task task = null;

            if (!this.CanEnableTreeItem)
                return;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    if (this.ActiveWorker != null)
                    {
                        criteria = ParameterManager.GetWorkerResetCommand(this.ActiveWorker.ServerConnectionId.Value, new long[] { this.ActiveWorker.WorkerId.Value }, !this.ActiveWorker.IsEnabled);
                        await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkerManager.ExecuteAsync(criteria);
                        using (var manager = new Sidvall.Business.BusinessSettingsManager(this.ActiveWorker, Sidvall.Business.BusinessEvents.NotifyPropertyChanged))
                        {
                            this.ActiveWorker.IsEnabled = !this.ActiveWorker.IsEnabled;
                        }
                        await ReloadAsync();
                    }
                    else if (this.ActiveWorkItem != null)
                    {
                        criteria = ParameterManager.GetWorkItemResetCommand(this.ActiveWorkItem.ServerConnectionId.Value, new long[] { this.ActiveWorkItem.WorkItemId.Value },
                            null, false, false, false, null, false, null, null, !this.ActiveWorkItem.IsEnabled);
                        await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemManager.ExecuteAsync(criteria);
                        using (var manager = new Sidvall.Business.BusinessSettingsManager(this.ActiveWorkItem, Sidvall.Business.BusinessEvents.NotifyPropertyChanged))
                        {
                            this.ActiveWorkItem.IsEnabled = !this.ActiveWorkItem.IsEnabled;
                        }
                        await ReloadAsync();
                    }
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region DeleteActiveTreeItemCommand

        public ICommand DeleteActiveTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await DeleteActiveTreeItemAsync());
            }
        }

        #endregion
        #region DeleteActiveTreeItemAsync

        public async Task DeleteActiveTreeItemAsync()
        {
            await DeleteTreeItemAsync(this.ActiveTreeItem);
        }

        #endregion
        #region ResetActiveTreeItemCommand

        public ICommand ResetActiveTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await ResetActiveTreeItemAsync());
            }
        }

        #endregion
        #region ResetActiveTreeItemAsync

        public async Task ResetActiveTreeItemAsync()
        {
            System.Collections.Generic.List<long> ids;
            CommandCriteria criteria;
            Task task = null;
            int serverConnectionId;

            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    serverConnectionId = -1;
                    ids = new System.Collections.Generic.List<long>();
                    if (this.ActiveServerConnection != null)
                    {
                        serverConnectionId = this.ActiveServerConnection.ServerConnectionId.Value;
                        foreach (var treeItem in this.TreeItems)
                        {
                            if ((treeItem.IsItem) && (treeItem.ServerConnectionId == serverConnectionId))
                                ids.Add(treeItem.ItemId.Value);
                        }
                    }
                    else if ((this.ActiveWorker != null) && (this.ActiveWorker.WorkerId != null))
                    {
                        serverConnectionId = this.ActiveWorker.ServerConnectionId.Value;
                        foreach (var treeItem in this.TreeItems)
                        {
                            if ((treeItem.IsItem) && (treeItem.WorkerId == this.ActiveWorker.WorkerId))
                                ids.Add(treeItem.ItemId.Value);
                        }
                    }
                    else if ((this.ActiveWorkItem != null) && (this.ActiveWorkItem.WorkItemId != null))
                    {
                        serverConnectionId = this.ActiveWorkItem.ServerConnectionId.Value;
                        ids.Add(this.ActiveWorkItem.WorkItemId.Value);
                    }
                    if (ids.Count > 0)
                    {
                        criteria = ParameterManager.GetWorkItemResetCommand(serverConnectionId, ids, Sidvall.WorkItemManager.Workflow.WorkItemStatus.Idle,
                            true, true, true, 0, true, false, false, null);
                        await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemManager.ExecuteAsync(criteria);
                        await ReloadAsync();
                    }
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region RunTreeItemCommand

        public ICommand RunTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await RunTreeItemAsync());
            }
        }

        #endregion
        #region RunTreeItemAsync

        public async Task RunTreeItemAsync()
        {
            CommandCriteria criteria;
            Task task = null;

            if (!this.CanRunTreeItem)
                return;
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    criteria = ParameterManager.GetWorkItemResetCommand(this.ActiveWorkItem.ServerConnectionId.Value, new long[] { this.ActiveWorkItem.WorkItemId.Value },
                        null, false, false, false, null, false, true, null, null);
                    await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemManager.ExecuteAsync(criteria);
                    await ReloadAsync();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region SaveActiveTreeItemCommand

        public ICommand SaveActiveTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await SaveActiveTreeItemAsync());
            }
        }

        #endregion
        #region SaveActiveTreeItemAsync

        public async Task SaveActiveTreeItemAsync()
        {
            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    if (this.ActiveWorker != null)
                    {
                        this.ActiveWorker = await this.ActiveWorker.SaveItemAsync();
                    }
                    else if (this.ActiveWorkItem != null)
                    {
                        this.ActiveWorkItem = await this.ActiveWorkItem.SaveItemAsync();
                        await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkItemManager.InitializeSensorsAsync(this.ActiveTreeItem.ServerConnectionId, this.ActiveWorkItem.WorkItemId.Value);
                        await RefreshWorkItemSensorsAsync(this.ActiveWorkItem);
                        InitializeRetryPolicy();
                        InitializeType();
                    }
                    await ReloadAsync();
                }
                catch (System.Exception ex)
                {
                    await Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
            }
        }

        #endregion
        #region SelectTreeItemCommand

        public ICommand SelectTreeItemCommand
        {
            get
            {
                return new MvxCommand(async () => await SelectTreeItemAsync());
            }
        }

        #endregion
        #region SelectTreeItemAsync

        public async Task SelectTreeItemAsync()
        {
            System.Collections.Generic.List<Sidvall.WorkItemManager.Data.Relations.WorkItemRelation> workItemRelations;
            WorkItem workItem;

            using (var busyManager = new BusyManager(this))
            {
                try
                {
                    if (this.ActiveTreeItem == null)
                    {
                        this.ActiveServerManager = null;
                        this.ActiveWorkItem = null;
                    }
                    else if (this.ActiveTreeItem.IsServer)
                    {
                        this.ActiveServerManager = ServerConnection.GetServerManager(this.ActiveTreeItem.ServerConnectionId);
                        this.ActiveServerConnection = ServerConnection.GetServerConnection(this.ActiveTreeItem.ServerConnectionId);
                    }
                    else if (this.ActiveTreeItem.IsWorker)
                    {
                        this.ActiveServerManager = ServerConnection.GetServerManager(this.ActiveTreeItem.ServerConnectionId);
                        this.ActiveWorker = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkerManager.GetItemByPrimaryKeyAsync(this.ActiveTreeItem.ServerConnectionId, this.ActiveTreeItem.WorkerId.Value);
                    }
                    else
                    {
                        this.ActiveServerManager = ServerConnection.GetServerManager(this.ActiveTreeItem.ServerConnectionId);
                        workItemRelations = new System.Collections.Generic.List<Data.Relations.WorkItemRelation>();
                        workItemRelations.Add(Data.Relations.WorkItemRelation.WorkItemWorkConditions);
                        workItemRelations.Add(Data.Relations.WorkItemRelation.WorkItemSensors);
                        workItem = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkItemManager.GetItemByPrimaryKeyAsync(this.ActiveTreeItem.ServerConnectionId, this.ActiveTreeItem.ItemId.Value, workItemRelations);
                        if (workItem != null)
                        {
                            await RefreshLogAsync(workItem);
                            foreach (var workItemCondition in workItem.WorkItemWorkConditions)
                                workItemCondition.Description = await this.ActiveTreeItem.ServerManager.GetWorkItemConditionDescriptionAsync(workItem, workItemCondition);
                        }
                        this.ActiveWorkItem = workItem;
                        InitializeRetryPolicy();
                        InitializeType();
                        this.ConditionListIsVisible = true;
                    }
                }
                catch (System.Exception ex)
                {
                    await Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
            }
        }

        #endregion
        #region MoveTreeItemAsync

        public async Task MoveTreeItemAsync(TreeItem sourceItem, TreeItem destinationItem)
        {
            Task task = null;
            if (sourceItem == null)
                return;
            if (destinationItem == null)
                return;
            if (!sourceItem.IsItem)
                return;
            if ((!destinationItem.IsItem) && (!destinationItem.IsWorker))
                return;
            if (destinationItem.TreeItemId == sourceItem.TreeItemId)
                return;
            using (var busyManager = new Sidvall.Data.BusyManager(this))
            {
                try
                {
                    var message = await Sidvall.UI.SystemContext.Current.DialogManager.ShowYesNoMessageAsync("Move Item", "Move item: " + sourceItem.Name + " to " + destinationItem.Name + ". Are you sure?",
                        Sidvall.UI.Dialogs.MessageType.Question, false);
                    if (!message.AnswerIsYes)
                        return;
                    await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemManager.MoveItemAsync(sourceItem.ServerConnectionId, sourceItem.WorkerId.Value, sourceItem.ItemId.Value,
                        destinationItem.ServerConnectionId, destinationItem.WorkerId.Value, destinationItem.ItemId);
                    await ReloadAsync();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Export Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion

        #region ReloadAsync

        public async Task ReloadAsync()
        {
            System.Collections.Generic.List<Sidvall.WorkItemManager.Data.Relations.WorkItemRelation> workItemRelations;
            WorkItem workItem;
            TreeItem treeItem;

            try
            {
                if (this.TreeItems == null)
                    return;
                await this.TreeItems.ReloadAsync(Sidvall.WorkItemManager.Data.TreeType.WorkItem);
                treeItem = this.TreeItems.FindItem(this.ActiveWorkItem);
                if (treeItem != null)
                {
                    workItemRelations = new System.Collections.Generic.List<Data.Relations.WorkItemRelation>();
                    workItemRelations.Add(Data.Relations.WorkItemRelation.WorkItemSensors);
                    workItem = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkItemManager.GetItemByPrimaryKeyAsync(treeItem.ServerConnectionId, treeItem.ItemId.Value, workItemRelations);
                    this.ActiveWorkItem.ImportResult(workItem);
                }
                this.LastUpdated = System.DateTime.Now;
                this.LastUpdatedException = null;
                RaisePropertyChanged(nameof(IdleTime));
            }
            catch (System.Exception ex)
            {
                this.LastUpdatedException = Sidvall.SystemContext.Current.SystemExceptionManager.GetMessage(ex);
            }
        }

        #endregion
        #region StartAsync

        protected override async Task StartAsync()
        {
            this.PublishChange = true;
            this.WorkItemIsVisible = false;
            this.LogPageSize = 100;
            this.LogFilterAll = true;

            this.TreeItems = TreeItemCollection.GetTreeItemCollection();
            this.Title = "Workers";
            var messenger = Mvx.Resolve<IMvxMessenger>();
            this.ViewModelResources.Add(messenger.Subscribe<WorkItemConditionContextMessage>(OnWorkItemConditionContextMessage));
            this.ViewModelResources.Add(messenger.Subscribe<WorkItemContextMessage>(OnWorkItemContextMessage));
            this.ViewModelResources.Add(messenger.Subscribe<WorkItemExecutionContextMessage>(OnWorkItemExecutionContextMessage));
            this.ViewModelResources.Add(messenger.Subscribe<WorkItemRetryPolicyContextMessage>(OnWorkItemRetryPolicyContextMessage));

            await ReloadAsync();
        }

        #endregion

        #endregion
        #region Private Members

        private long? CurrentConditionId { get; set; }
        private long? CurrentRetryPolicyId { get; set; }
        private long? CurrentWorkItemTypeId { get; set; }
        private int LogPageSize { get; set; }
        private bool PublishChange { get; set; }
        private bool InitializingLogModes { get; set; }

        #region LogCurrentEndPosition

        private long LogCurrentEndPosition
        {
            get
            {
                if (this.LogCurrentStartPosition < 1)
                    return 0;
                if (this.LogCurrentPage >= this.LogPageCount)
                    return this.ActiveWorkItem.WorkItemLogs.TotalRowCount;
                return this.LogCurrentStartPosition + this.LogPageSize - 1;
            }
        }

        #endregion
        #region LogCurrentStartPosition

        private long LogCurrentStartPosition
        {
            get
            {
                if (this.LogCurrentPage < 1)
                    return 0;
                return (this.LogCurrentPage - 1) * this.LogPageSize + 1;
            }
        }

        #endregion
        #region LogCurrentPage

        private long _LogCurrentPage;
        private long LogCurrentPage
        {
            get
            {
                if (_LogCurrentPage > this.LogPageCount)
                    _LogCurrentPage = 1;
                return _LogCurrentPage;
            }
            set
            {
                _LogCurrentPage = value;
            }
        }

        #endregion
        #region LogPageCount

        private long LogPageCount
        {
            get
            {
                if (this.ActiveWorkItem == null)
                    return 0;
                if (this.ActiveWorkItem.WorkItemLogs == null)
                    return 0;
                if (this.ActiveWorkItem.WorkItemLogs.TotalRowCount % this.LogPageSize > 0)
                    return this.ActiveWorkItem.WorkItemLogs.TotalRowCount / this.LogPageSize + 1;
                return this.ActiveWorkItem.WorkItemLogs.TotalRowCount / this.LogPageSize;
            }
        }

        #endregion

        #region DeleteTreeItemAsync

        private async Task DeleteTreeItemAsync(TreeItem item)
        {
            if (item == null)
                return;
            if (item.IsServer)
                return;
            var message = await Sidvall.UI.SystemContext.Current.DialogManager.ShowYesNoMessageAsync("Remove item: " + item.Name, "Are you sure?",
                Sidvall.UI.Dialogs.MessageType.Question, false);
            if (!message.AnswerIsYes)
                return;
            if (item.IsWorker)
            {
                await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkerManager.DeleteItemByPrimaryKeyAsync(item.ServerConnectionId,
                    item.WorkerId.Value);
                if ((this.ActiveWorker != null) && (this.ActiveWorker.WorkerId == item.WorkerId))
                    this.ActiveWorker = null;
                await ReloadAsync();
            }
            else if (item.IsItem)
            {
                await Sidvall.WorkItemManager.SystemContext.Current.DataPortal.WorkItemManager.DeleteItemByPrimaryKeyAsync(item.ServerConnectionId,
                    item.ItemId.Value);
                if ((this.ActiveWorkItem != null) && (this.ActiveWorkItem.WorkItemId == item.ItemId))
                    this.ActiveWorkItem = null;
                await ReloadAsync();
            }
        }

        #endregion
        #region InitializeCondition

        private void InitializeCondition()
        {
            System.Type type;
            ContextParameter parameter;

            if (this.ActiveWorkItemCondition == null)
                return;

            // WorkItemConditionContextContent
            if (this.ActiveWorkItemCondition.WorkConditionId != this.CurrentConditionId)
            {
                this.CurrentConditionId = this.ActiveWorkItemCondition.WorkConditionId;

                type = this.ActiveTreeItem.ServerManager.GetWorkItemConditionContextEditor(this.ActiveWorkItemCondition.WorkConditionId);
                parameter = new ContextParameter()
                {
                    ServerConnectionId = this.ActiveWorkItem.ServerConnectionId.ToString(),
                    Context = this.ActiveWorkItemCondition.ConditionContext,
                };
                if (type != null)
                    ShowViewModel(type, parameter, false, "CenterContent.WorkItemConditionContextContent");
                else
                    ShowViewModel<Sidvall.WorkItemManager.UI.ViewModels.Conditions.WorkItemConditionContextViewModel>(parameter, false, "CenterContent.WorkItemConditionContextContent");
            }
            else if (this.PublishChange)
            {
                var messenger = Mvx.Resolve<IMvxMessenger>();
                var message = new WorkItemConditionContextMessage(this)
                {
                    Context = this.ActiveWorkItemCondition.ConditionContext,
                };
                messenger.Publish<WorkItemConditionContextMessage>(message);
            }
        }

        #endregion
        #region InitializeRetryPolicy

        private void InitializeRetryPolicy()
        {
            System.Type type;
            ContextParameter parameter;

            if (this.ActiveTreeItem == null)
                return;
            if (this.ActiveWorkItem == null)
                return;

            // RetryPolicyContent
            if (this.ActiveWorkItem.WorkRetryPolicyId == null)
            {
                ChangePresentation(Sidvall.UI.ViewModels.ViewModelActionType.CloseView, "CenterContent.RetryPolicyContent");
                this.CurrentRetryPolicyId = null;
            }
            else if (this.ActiveWorkItem.WorkRetryPolicyId != this.CurrentRetryPolicyId)
            {
                this.CurrentRetryPolicyId = this.ActiveWorkItem.WorkRetryPolicyId;

                type = this.ActiveTreeItem.ServerManager.GetWorkItemRetryPolicyContextEditor(this.ActiveWorkItem.WorkRetryPolicyId.Value);
                parameter = new ContextParameter()
                {
                    ServerConnectionId = this.ActiveWorkItem.ServerConnectionId.ToString(),
                    Context = this.ActiveWorkItem.WorkRetryPolicyContext,
                };
                if (type != null)
                    ShowViewModel(type, parameter, false, "CenterContent.RetryPolicyContent");
            }
            else
            {
                PublishRetryPolicy();
            }
        }

        #endregion
        #region InitializeType

        private void InitializeType()
        {
            System.Type type;
            ContextParameter parameter;

            if (this.ActiveTreeItem == null)
                return;
            if (this.ActiveWorkItem == null)
                return;

            if (this.ActiveWorkItem.WorkItemTypeId == null)
            {
                ChangePresentation(Sidvall.UI.ViewModels.ViewModelActionType.CloseView, "CenterContent.WorkItemContextContent");
                ChangePresentation(Sidvall.UI.ViewModels.ViewModelActionType.CloseView, "CenterContent.WorkItemExecutionContextContent");
                this.CurrentWorkItemTypeId = null;
            }
            else if (this.ActiveWorkItem.WorkItemTypeId != this.CurrentWorkItemTypeId)
            {
                this.CurrentWorkItemTypeId = this.ActiveWorkItem.WorkItemTypeId;

                // WorkItemContextContent
                type = this.ActiveTreeItem.ServerManager.GetWorkItemContextEditor(this.ActiveWorkItem.WorkItemTypeId);
                parameter = new ContextParameter()
                {
                    ServerConnectionId = this.ActiveWorkItem.ServerConnectionId.ToString(),
                    Context = this.ActiveWorkItem.WorkItemContext,
                };
                if (type != null)
                    ShowViewModel(type, parameter, false, "CenterContent.WorkItemContextContent");
                else
                    ShowViewModel<Sidvall.WorkItemManager.UI.ViewModels.WorkItems.WorkItemContextViewModel>(parameter, false, "CenterContent.WorkItemContextContent");

                // WorkItemExecutionContextContent
                type = this.ActiveTreeItem.ServerManager.GetWorkItemExecutionContextEditor(this.ActiveWorkItem.WorkItemTypeId);
                parameter = new ContextParameter()
                {
                    ServerConnectionId = this.ActiveWorkItem.ServerConnectionId.ToString(),
                    Context = this.ActiveWorkItem.ExecutionContext,
                };
                if (type != null)
                    ShowViewModel(type, parameter, false, "CenterContent.WorkItemExecutionContextContent");
                else
                    ShowViewModel<Sidvall.WorkItemManager.UI.ViewModels.WorkItems.WorkItemExecutionContextViewModel>(parameter, false, "CenterContent.WorkItemExecutionContextContent");
            }
            else
            {
                PublishType();
            }
        }

        #endregion
        #region InitializeLog

        private void InitializeLog()
        {
            if (this.ActiveWorkItem == null)
                return;
            this.InitializingLogModes = true;
            foreach (var item in this.LogModes)
            {
                if ((this.ActiveWorkItem.LogModeId & item.Value) == item.Value)
                    item.IsSelected = true;
                else
                    item.IsSelected = false;
            }
            this.InitializingLogModes = false;
            this.LogCurrentPage = 1;
        }

        #endregion
        #region PublishRetryPolicy

        private void PublishRetryPolicy()
        {
            if (!this.PublishChange)
                return;
            if (this.ActiveWorkItem == null)
                return;

            var messenger = Mvx.Resolve<IMvxMessenger>();
            var message = new WorkItemRetryPolicyContextMessage(this)
            {
                Context = this.ActiveWorkItem.WorkRetryPolicyContext,
            };
            messenger.Publish<WorkItemRetryPolicyContextMessage>(message);
        }

        #endregion
        #region PublishType

        private void PublishType()
        {
            if (!this.PublishChange)
                return;
            if (this.ActiveWorkItem == null)
                return;

            var contextMessage = new WorkItemContextMessage(this)
            {
                Context = this.ActiveWorkItem.WorkItemContext,
                CanEdit = this.CanEdit,
            };
            Publish(contextMessage);

            var executionContextMessage = new WorkItemExecutionContextMessage(this)
            {
                Context = this.ActiveWorkItem.ExecutionContext,
            };
            Publish(executionContextMessage);
        }

        #endregion

        #region OnLogModesChildChanged

        private void OnLogModesChildChanged(object sender, Sidvall.Business.ChildChangedEventArgs e)
        {
            Sidvall.WorkItemManager.Workflow.LogModes logModes;

            if (this.InitializingLogModes)
                return;
            if (this.ActiveWorkItem == null)
                return;
            logModes = Workflow.LogModes.None;
            foreach (var item in this.LogModes.SelectedValues)
                logModes = logModes | item;
            this.ActiveWorkItem.LogModeId = logModes;
        }

        #endregion
        #region OnActiveWorkItemPropertyChanged

        private void OnActiveWorkItemPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(e.PropertyName))
                return;
            switch (e.PropertyName)
            {
                case "ExecutionContext":
                case "WorkItemContext":
                    PublishType();
                    break;
                case "RetryPolicyContext":
                    PublishRetryPolicy();
                    break;
                default:
                    break;
            }
            RaisePropertyChanged("Title");
            RaisePropertyChanged("TreeItems");
            RaisePropertyChanged("ActiveTreeItem");
            RaisePropertyChanged("ActiveWorkItemCondition");
            RaisePropertyChanged("LastUpdated");
            RaisePropertyChanged("LastUpdatedException");
            RaisePropertyChanged("LastUpdatedExceptionIsVisible");
            RaisePropertyChanged("InformationIsVisible");
            RaisePropertyChanged("ServerIsVisible");
            RaisePropertyChanged("WorkerIsVisible");
            RaisePropertyChanged("WorkItemIsVisible");
            RaisePropertyChanged("CanSave");
            RaisePropertyChanged("CanDelete");
            RaisePropertyChanged("CanDeleteLogs");
            RaisePropertyChanged("CanEdit");
            RaisePropertyChanged("CanReset");
            RaisePropertyChanged("CanAddTreeItem");
            RaisePropertyChanged("CanCancelTreeItem");
            RaisePropertyChanged("CanEnableTreeItem");
            RaisePropertyChanged("CanRunTreeItem");
            RaisePropertyChanged("CanDeleteRetryPolicy");
            RaisePropertyChanged("CanPageBackLog");
            RaisePropertyChanged("CanPageForwardLog");
            RaisePropertyChanged("AddTreeItemCaption");
            RaisePropertyChanged("TreeItemIsEnabled");
            RaisePropertyChanged("LogCaption");
            RaisePropertyChanged("ConditionListIsVisible");
            RaisePropertyChanged("ThreadActions");
            RaisePropertyChanged("WorkItemStatuses");
            RaisePropertyChanged("LogModes");
            RaisePropertyChanged("LogFilterAll");
            RaisePropertyChanged("LogFilterErrors");
            RaisePropertyChanged("LogFilterMessages");
        }

        #endregion
        #region OnActiveWorkerPropertyChanged

        private void OnActiveWorkerPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            RaiseAllPropertiesChanged();
        }

        #endregion
        #region OnTreeItemsCollectionChanging

        private async void OnTreeItemsCollectionChanging(object sender, Sidvall.Business.CollectionChangedEventArgs e)
        {
            if (e.Action == Sidvall.Business.CollectionChangedAction.RemoveItem)
            {
                await DeleteTreeItemAsync(e.Item as TreeItem);
                e.Cancel = true;
            }
        }

        #endregion
        #region OnWorkItemConditionContextMessage

        private void OnWorkItemConditionContextMessage(WorkItemConditionContextMessage item)
        {
            if (this.ActiveWorkItemCondition == null)
                return;

            this.PublishChange = false;
            this.ActiveWorkItemCondition.ConditionContext = item.Context;
            this.PublishChange = true;
        }

        #endregion
        #region OnWorkItemContextMessage

        private void OnWorkItemContextMessage(WorkItemContextMessage item)
        {
            if (this.ActiveWorkItem == null)
                return;
            if (!this.CanEdit)
                return;

            this.PublishChange = false;
            this.ActiveWorkItem.WorkItemContext = item.Context;
            this.PublishChange = true;
        }

        #endregion
        #region OnWorkItemExecutionContextMessage

        private void OnWorkItemExecutionContextMessage(WorkItemExecutionContextMessage item)
        {
            if (this.ActiveWorkItem == null)
                return;

            this.PublishChange = false;
            this.ActiveWorkItem.ExecutionContext = item.Context;
            this.PublishChange = true;
        }

        #endregion
        #region OnWorkItemRetryPolicyContextMessage

        private void OnWorkItemRetryPolicyContextMessage(WorkItemRetryPolicyContextMessage item)
        {
            if (this.ActiveWorkItem == null)
                return;

            this.PublishChange = false;
            this.ActiveWorkItem.WorkRetryPolicyContext = item.Context;
            this.PublishChange = true;
        }

        #endregion

        #region RefreshLogAsync

        private async Task RefreshLogAsync(WorkItem item)
        {
            WorkItemLogCollection items;

            if (item == null)
                return;
            if (item.WorkItemId == null)
                return;
            if (this.LogFilterErrors)
            {
                items = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkItemLogManager.GetItemsAsync(item.ServerConnectionId, item.WorkItemId, null, null,
                    WorkItemResultType.Failed, true, this.LogPageSize, (int)this.LogCurrentStartPosition - 1);
            }
            else if (this.LogFilterMessages)
            {
                items = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkItemLogManager.GetItemsAsync(item.ServerConnectionId, item.WorkItemId, null, false,
                    null, true, this.LogPageSize, (int)this.LogCurrentStartPosition - 1);
            }
            else
            {
                items = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkItemLogManager.GetItemsAsync(item.ServerConnectionId, item.WorkItemId, null, null,
                    null, true, this.LogPageSize, (int)this.LogCurrentStartPosition - 1);
            }
            item.LoadWorkItemLogs(items);
        }

        #endregion
        #region RefreshWorkItemSensorsAsync

        private async Task RefreshWorkItemSensorsAsync(WorkItem item)
        {
            if (item == null)
                return;
            if (item.WorkItemId == null)
                return;

            var criteria = new FetchListCriteria<Data.Fields.WorkItemSensorField, Data.Relations.WorkItemSensorRelation>();
            criteria.SortItems = new SortItemCollection<Data.Fields.WorkItemSensorField>();
            criteria.SortItems.Add(Data.Fields.WorkItemSensorField.Name, true);
            ParameterManager.InitializeParameters(criteria, item.ServerConnectionId.Value);

            var items = await Sidvall.WorkItemManager.UI.SystemContext.Current.DataPortal.WorkItemSensorManager.GetItemsAsync(criteria);
            item.LoadWorkItemSensors(items);
        }

        #endregion

        #endregion
    }
}